package co.fitstart.admin.web.controller.course;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.demo2do.core.BusinessException;
import com.demo2do.core.support.Result;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.JsonUtils;
import co.fitstart.admin.cache.accessor.PersistentAccessor;
import co.fitstart.admin.entity.security.Login;
import co.fitstart.admin.service.CoachService;
import co.fitstart.admin.service.CourseRoundService;
import co.fitstart.admin.service.CourseScheduleService;
import co.fitstart.admin.service.OfflineRoundService;
import co.fitstart.admin.service.PrincipalService;
import co.fitstart.admin.service.SiteService;
import co.fitstart.admin.web.resolver.Secure;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.site.Site;

/**
 * 
 * @author mohanlan
 *
 */
@Controller
@RequestMapping("/individual-rounds/{courseRoundId}")
public class IndividualRoundEditController {
    
    private static final Logger logger = LoggerFactory.getLogger(IndividualRoundEditController.class);
    
    @Autowired
    private PrincipalService principalService;
    
    @Autowired
    private CourseScheduleService courseScheduleService;
    
    @Autowired
    private CourseRoundService courseRoundService;
    
    @Autowired
    private OfflineRoundService offlineRoundService;
    
    @Autowired
    private CoachService coachService;
    
    @Autowired
    private PersistentAccessor persistenceAccessor;
    
    @Autowired
    private SiteService siteService;
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/schedules/create", method = RequestMethod.GET)
    public ModelAndView create(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/schedule-create");
        modelAndView.addObject("pagetype", "individual");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param amount
     * @return
     */
    @RequestMapping(value = "/schedules", method = RequestMethod.POST)
    public @ResponseBody String onCreate(@PathVariable("courseRoundId") Long courseRoundId,
                           @RequestParam("amount") int amount) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseScheduleService.addSchedule(courseRound, amount);
            
            // TODO send message
            
            result.success().message("增加课程成功");
            
        } catch(BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            logger.error("onCreate() error:", e);
            result.fail().message("增加课程失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId 
     * @param scheduleId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/coach", method = RequestMethod.GET)
    public ModelAndView editScheduleCoach(@PathVariable("courseRoundId") Long courseRoundId,
                                         @PathVariable("scheduleId") Long scheduleId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/schedule-coach-edit");
        modelAndView.addObject("pagetype", "individual");
        CourseSchedule courseSchedule = courseScheduleService.load(CourseSchedule.class, scheduleId);
        modelAndView.addObject("schedule", courseSchedule);
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        Site site = courseSchedule.getSite();
        
        // Get all coaches in this site
        Map<String, Principal> coachMap = persistenceAccessor.coaches(courseSchedule.getCoach().getId(), site.getId());
        List<Principal> coaches = new ArrayList<Principal>(coachMap.values());
        
        Date day = courseSchedule.getOccurDate();
        String hour = courseSchedule.getOccurHour();
       
        // Get available coaches at this moment in this site
        List<Principal> availableCoaches = courseScheduleService.getAvailableScheduleCoach(site, day, hour, coaches);
        
        modelAndView.addObject("coaches", availableCoaches);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param scheduleId 
     * @param coachId 
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/coach", method = RequestMethod.PATCH)
    public @ResponseBody String onEditScheduleCoach(@PathVariable("scheduleId") Long scheduleId,
                                                    @RequestParam("coachId") Long coachId) {
        
        Result result = new Result();
        
        try {
            
            CourseSchedule courseSchedule = courseScheduleService.load(CourseSchedule.class, scheduleId);
            
            Principal coach = principalService.load(Principal.class, coachId);
            
            courseScheduleService.changeCoach(courseSchedule, coach);
            
            // init corp user ids by principal
            List<String> userids = new ArrayList<String>();
            userids.add(courseSchedule.getCoach().getMobile());
            
            // TODO send crop message by status
            
            result.success().message("修改课程教练成功");
            
        } catch (Exception e) {
            
            logger.error("onEditScheduleCoach() error:", e);
            result.fail().message("修改课程教练失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId 
     * @param roundCode 
     * @param dayhour 
     * @return
     */
    @RequestMapping(value = "/schedules/{roundCode}/time", method = RequestMethod.GET)
    public ModelAndView editScheduleTime(@PathVariable("courseRoundId") Long courseRoundId,
                                         @PathVariable("roundCode") String roundCode,
                                         @RequestParam("dayhour") String dayhour) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/schedule-time-edit");
        modelAndView.addObject("pagetype", "individual");
        List<CourseRound> courseRounds = offlineRoundService.listCourseRound(roundCode);
        List<CourseSchedule> courseSchedules = courseScheduleService.listCourseSchedule(courseRounds, dayhour);
        modelAndView.addObject("schedule", courseSchedules.get(0));
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("dayhour", dayhour);
        
        modelAndView.addObject("courseRoundId", courseRoundId);
        modelAndView.addObject("site", courseRounds.get(0).getSite());
        
        return modelAndView;
    }
    
    /**
     * 
     * @param roundCode 
     * @param dayhour 
     * @param day 
     * @param hour 
     * @return
     */
    @RequestMapping(value = "/schedules/{roundCode}/time", method = RequestMethod.PATCH)
    public @ResponseBody String onEditScheduleTime(@PathVariable("roundCode") String roundCode,
                                                   @RequestParam(value = "dayhour") String dayhour,
                                                   @RequestParam("day") @DateTimeFormat(pattern = "yyyy-MM-dd") Date day,
                                                   @RequestParam("hour") String hour) {
        
        Result result = new Result();
        
        try {
            
            // step1 list selected course schedule
            List<CourseRound> courseRounds = offlineRoundService.listCourseRound(roundCode);
            List<CourseSchedule> courseSchedules = courseScheduleService.listCourseSchedule(courseRounds, dayhour);
            
            String selectedDayHour = DateFormatUtils.format(day) + "|" + hour;
            
            Principal coach = courseSchedules.get(0).getCoach();
            
            // setp2 check coach is available or not by dayhour
            List<String> dayhours = courseRoundService.getDayhours(StringUtils.replace(dayhour, "|", " "));
            if(StringUtils.equalsIgnoreCase(dayhour, selectedDayHour) || (dayhours.contains(selectedDayHour) && courseRoundService.validateCoach(coach, dayhours, dayhour, selectedDayHour)) ) {
                //    选中时间 等于 原来时间 或 （原来时间前后半小时 内 有课）
                result.success();
            } else if(coach != null) {
                result = courseRoundService.validateCoach(coach, selectedDayHour);
            }
            
            // step3 do bind coach if validateCoach success
            if(result.isValid()) {
                courseRoundService.changeScheduleTime(courseSchedules, day, hour, CourseType.INDIVIDUAL);
                result.success().message("修改课程时间成功");
            }
            
            // init corp user ids by principal
            List<String> userids = new ArrayList<String>();
            userids.add(courseSchedules.get(0).getCoach().getMobile());
            
            // TODO send crop message by status
            
        } catch (BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            logger.error("onEditScheduleTime() error:", e);
            result.fail().message("修改课程时间失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId 
     * @param scheduleId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/edit", method = RequestMethod.GET)
    public ModelAndView editSchedule(@PathVariable("courseRoundId") Long courseRoundId,
                                     @PathVariable("scheduleId") Long scheduleId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/schedule-edit");
        modelAndView.addObject("pagetype", "individual");
        CourseSchedule courseSchedule = courseScheduleService.load(CourseSchedule.class, scheduleId);
       
        modelAndView.addObject("schedule", courseSchedule);
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        Site site = courseSchedule.getSite();
        modelAndView.addObject("site", site);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param coachId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/coach-site", method = RequestMethod.POST)
    public @ResponseBody String coachSite(@RequestParam("coachId") Long coachId,
                                          @RequestParam(value = "occurDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date occurDate) {
        
        Result result = new Result();
        
        try {
            
            Principal coach = principalService.load(Principal.class, coachId);
            
            List<Site> sites = coachService.listCoachSite(coach, occurDate);
            
            result.success().data("sites", sites).data("siteAmount", sites.size()).message("获取教练门店成功");
            
        } catch (Exception e) {
            
            logger.error("coachSite() error:", e);
            result.fail().message("获取教练门店失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param scheduleId 
     * @param coachId 
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}", method = RequestMethod.PATCH)
    public @ResponseBody String onEditSchedule(@PathVariable("scheduleId") Long scheduleId,
                                               @RequestParam("coachId") Long coachId,
                                               @RequestParam(name = "siteId", required = false) Long siteId,
                                               @RequestParam("day") @DateTimeFormat(pattern = "yyyy-MM-dd") Date day,
                                               @RequestParam("hour") String hour) {
        
        Result result = new Result();
        
        try {
            
            CourseSchedule courseSchedule = courseScheduleService.load(CourseSchedule.class, scheduleId);
            
            Principal coach = principalService.load(Principal.class, coachId);
            
            Site site = null;
            if(siteId != null) {
                site = siteService.load(siteId);
            } else {
                site = coachService.getCoachSite(coach);
            }
            
            courseRoundService.validateEditSchedule(courseSchedule, coach, day, hour, site);
            
            courseScheduleService.editSchedule(courseSchedule, coach, site, day, hour);
            
            result.success().message("修改课程成功");
            
        } catch (BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            logger.error("onEditSchedule() error:", e);
            result.fail().message("修改课程失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId 
     * @param scheduleId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/cancel", method = RequestMethod.GET)
    public ModelAndView cancel(@PathVariable("courseRoundId") Long courseRoundId,
                               @PathVariable("scheduleId") Long scheduleId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/schedule-cancel");
        modelAndView.addObject("pagetype", "individual");
        modelAndView.addObject("scheduleId", scheduleId);
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param scheduleId 
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/cancel", method = RequestMethod.PATCH)
    public @ResponseBody String onCancel(@PathVariable("scheduleId") Long scheduleId) {
        
        Result result = new Result();
        
        try {
            
            CourseSchedule courseSchedule = courseScheduleService.load(CourseSchedule.class, scheduleId);
            
            courseScheduleService.cancel(courseSchedule);
            
            result.success().message("取消课程成功");
            
        } catch (Exception e) {
            
            logger.error("onCancel() error:", e);
            result.fail().message("取消课程失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * view generate schedule 
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value ="/schedules/{scheduleId}/generate", method = RequestMethod.GET)
    public ModelAndView generateSchedules(@PathVariable("courseRoundId") Long courseRoundId,
                                   @PathVariable("scheduleId") Long scheduleId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/action-generate");
        modelAndView.addObject("pagetype", "individual");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * do generate the action of schedule 
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/generate", method = RequestMethod.PATCH)
    public @ResponseBody String onGenerateSchedules(@PathVariable("courseRoundId") Long courseRoundId,
                                                    @PathVariable("scheduleId") Long scheduleId) {
        
        Result result = new Result();
        
        try {
            
            result.success().message("生成课件成功");
            
        } catch (Exception e) {
            
            logger.error("onCancel() error:", e);
            result.fail().message("生成课件失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * view the action of schedule create
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value ="/schedules/{scheduleId}/actions/create", method = RequestMethod.GET)
    public ModelAndView createAction(@PathVariable("courseRoundId") Long courseRoundId,
                                     @PathVariable("scheduleId") Long scheduleId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/action-create");
        modelAndView.addObject("pagetype", "individual");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    
    
    /**
     * do create the action of schedule 
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/actions", method = RequestMethod.POST)
    public @ResponseBody String onCreateAction(@PathVariable("courseRoundId") Long courseRoundId,
                                               @PathVariable("scheduleId") Long scheduleId) {
        
        Result result = new Result();
        
        try {
            
            result.success().message("新增动作成功");
            
        } catch (Exception e) {
            
            logger.error("onCancel() error:", e);
            result.fail().message("删除动作失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * view the action of schedule edit
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value ="/schedules/{scheduleId}/actions/{actionId}/edit", method = RequestMethod.GET)
    public ModelAndView editAction(@PathVariable("courseRoundId") Long courseRoundId,
                                   @PathVariable("scheduleId") Long scheduleId,
                                   @PathVariable("actionId") Long actionId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/action-edit");
        modelAndView.addObject("pagetype", "individual");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * do the action of schedule edit
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/actions/{actionId}", method = RequestMethod.PATCH)
    public @ResponseBody String onEditAction(@PathVariable("courseRoundId") Long courseRoundId,
                                             @PathVariable("scheduleId") Long scheduleId,
                                             @PathVariable("actionId") Long actionId) {
        
        Result result = new Result();
        
        try {
            
            result.success().message("修改动作成功");
            
        } catch (Exception e) {
            
            logger.error("onCancel() error:", e);
            result.fail().message("修改动作失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    
    /**
     * view delete the action of schedule
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value ="/schedules/{scheduleId}/actions/{actionId}/delete", method = RequestMethod.GET)
    public ModelAndView deleteAction(@PathVariable("courseRoundId") Long courseRoundId,
                                     @PathVariable("scheduleId") Long scheduleId,
                                     @PathVariable("actionId") Long actionId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/action-delete");
        modelAndView.addObject("pagetype", "individual");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * do delete the action of schedule 
     * 
     * @param courseRoundId
     * @param scheduleId
     * @param actionId
     * @return
     */
    @RequestMapping(value = "/schedules/{scheduleId}/actions/{actionId}", method = RequestMethod.DELETE)
    public @ResponseBody String onDeleteAction(@PathVariable("courseRoundId") Long courseRoundId,
                                               @PathVariable("scheduleId") Long scheduleId,
                                               @PathVariable("actionId") Long actionId) {
        Result result = new Result();
        
        try {
            
            result.success().message("删除动作成功");
            
        } catch (Exception e) {
            
            logger.error("onCancel() error:", e);
            result.fail().message("删除动作失败");
        }
        
        return JsonUtils.toJsonString(result);
    }

    /**
     * 绑定主课程(仅赠课)
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/bind-main", method = RequestMethod.GET)
    public ModelAndView bindMain(@Secure Login login,
                                 @PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-bind-main");
        modelAndView.addObject("pagetype", "individual");
        List<CourseRound> mains = new ArrayList<>();
        CourseRound give = courseRoundService.loadCourseRound(courseRoundId);
        
        if(login.hasSite()) {
            mains = courseRoundService.listMain(give.getStudent(), login.getSite());
        } else if(login.isAreaServer() || login.isAreaManager()) {
            Principal principal = principalService.load(Principal.class, login.getId());
            
            List<Site> sites = siteService.listSite(principal);
            if(!sites.isEmpty()) {
                mains = courseRoundService.listMain(give.getStudent(), sites);
            }
        } else {
            mains = courseRoundService.listMain(give.getStudent());
        }
        
        modelAndView.addObject("courseRoundId", courseRoundId);
        modelAndView.addObject("mains", mains);
        
        return modelAndView;
    }

    /**
     * 
     * @param courseRoundId
     * @param mainCourseRoundId
     * @return
     */
    @RequestMapping(value = "/bind-main", method = RequestMethod.PATCH)
    public @ResponseBody String onBindMain(@Secure Login login,
                                           @PathVariable("courseRoundId") Long courseRoundId,
                                           @RequestParam("mainCourseRoundId") Long mainCourseRoundId) {
        
        Result result = new Result();
        
        try {
            
            CourseRound give = courseRoundService.loadCourseRound(courseRoundId);
            CourseRound main = courseRoundService.loadCourseRound(mainCourseRoundId);
            
            List<Site> sites = new ArrayList<>();
            if(login.hasSite()) {
                sites.add(siteService.load(login.getSite().getId()));
            } else if(login.isAreaServer() || login.isAreaManager()) {
                Principal principal = principalService.load(Principal.class, login.getId());
                
                sites = siteService.listSite(principal);
            }
            
            if(login.isRoot() || login.isAdmin() || (sites.contains(give.getSite()) && sites.contains(main.getSite()))) {
                courseRoundService.bindMain(give, main);
                
                result.success().message("绑定主课程成功");
            } else {
                result.fail().message("不可操作的门店");
            }
            
        } catch (BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            logger.error("onBindMain() error:", e);
            result.fail().message("绑定主课程失败");
        }
        
        return JsonUtils.toJsonString(result);
        
    }

    /**
     * 解绑主课程
     * @param login
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/unbind-main", method = RequestMethod.GET)
    public ModelAndView unbindMain(@Secure Login login,
                                   @PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-unbind-main");
        modelAndView.addObject("pagetype", "individual");
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        return modelAndView;
    }

    /**
     * 解绑
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/unbind-main", method = RequestMethod.PATCH)
    public @ResponseBody String onUnbindMain(@Secure Login login,
                                             @PathVariable("courseRoundId") Long courseRoundId) {
        
        Result result = new Result();
        
        try {
            
            CourseRound give = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.unbindMain(give);
            
            result.success().message("解绑主课程成功");
            
        } catch (Exception e) {
            
            logger.error("onUnbindMain() error:", e);
            result.fail().message("解绑主课程失败");
        }
        
        return JsonUtils.toJsonString(result);
        
    }

    /**
     * 手动初始化线上计划（仅root可操作）
     * @param login
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/init-courseware", method = RequestMethod.GET)
    public @ResponseBody String onInitCourseware(@Secure Login login,
                                                 @PathVariable("courseRoundId") Long courseRoundId) {
        
        Result result = new Result();
        
        try {
            if(login.isRoot() || login.isAdmin()) {
                CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
                
                courseRoundService.rootInitCourseware(courseRound);
                
                result.success().message("初始化线上计划成功");
            } else {
                result.fail().message("暂无权限");
            }
        } catch (Exception e) {
            
            logger.error("onInitCourseware() error:", e);
            result.fail().message("初始化线上计划失败");
        }
        
        return JsonUtils.toJsonString(result);
        
    }
}
